package com.zoweunion.mechanic.util.wx;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.wxpay.sdk.WXPay;
import com.zoweunion.mechanic.MechanicApplication;
import com.zoweunion.mechanic.config.AlipayConfig;
import com.zoweunion.mechanic.config.wx.WXPayConfig;
import com.zoweunion.mechanic.dao.PromotionCouponDao;
import com.zoweunion.mechanic.dao.UserCouponDao;
import com.zoweunion.mechanic.dao.app.TSSsInsuranceDao;
import com.zoweunion.mechanic.dao.order.CGOrderDao;
import com.zoweunion.mechanic.entity.PromotionCouponEntity;
import com.zoweunion.mechanic.entity.UserCouponEntity;
import com.zoweunion.mechanic.model.User;
import com.zoweunion.mechanic.service.app.AppService;
import com.zoweunion.mechanic.util.MyException;
import com.zoweunion.mechanic.util.Orgin;
import com.zoweunion.mechanic.util.certificate.OrderPay;
import com.zoweunion.mechanic.util.constants.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.zoweunion.mechanic.config.AlipayConfig.alipay_public_key;

@Component
public class WXPayService {
	@Autowired
	private WXPay wxPay;
	@Autowired
	private CGOrderDao cgOrderDao;
    @Autowired
	private TSSsInsuranceDao tsSsInsuranceDao;
    @Autowired
	private UserCouponDao userCouponDao;
	@Autowired
	private PromotionCouponDao promotionCouponDao;


	@Autowired
    private AppService appService;
	protected static Logger logger = LoggerFactory.getLogger(MechanicApplication.class);

	/**
	 * 发起支付请求 body 商品描述 out_trade_no 订单号 total_fee 订单金额 单位 元 product_id 商品ID
	 */
	public Map<String, String>  sendPayment(String body, String outTradeNo, double totalFee,
										   String productId,Integer payType,User currentUser,double paymentAmount,Long couponId)
			throws Exception {
		Map<String, String> reqData = wxUnifiedOrderParam(body, outTradeNo, totalFee, productId);
		try {
			Map<String, Object> tradeByNo = cgOrderDao.selectTradeByNo(outTradeNo);
			if (tradeByNo==null){
                cgOrderDao.insertCertificateOrderPay(OrderPay.builder()
                        .paymentAmount(new Double(paymentAmount*100).intValue())
                        .paymentReal(new Double(totalFee*100).intValue())
                        .couponId(couponId)
                        .paymentType(1)
                        .paymentTime(new Date())
                        .tradeNo(outTradeNo)
                        .orderType(payType)
                        .isRefund(1)
						.createUser(currentUser.getId())
                        .build());
                if (couponId!=0){
					userCouponDao.updateById(UserCouponEntity.builder()
							.id(couponId)
							.useFlag(2)
							.build());
				}
            }
		} catch (Exception e) {
			e.printStackTrace();
		}

		return wxPay.unifiedOrder(reqData);
	}

	/**
	 * 回调设置
	 *
	 * @return
	 * @throws Exception
	 */
	public Map<String, String> backPayment(String outTradeNo) throws Exception {
		Map<String, String> reqData = wxParamBack(outTradeNo);
		return wxPay.orderQuery(reqData);
	}

	/**
	 * 微信 统一下单 参数设置
	 * @param description
	 * @param outTradeNo
	 * @param totalFee
	 * @param productId
	 * @return
	 * @throws Exception
	 */
	public Map<String, String> wxUnifiedOrderParam(String description, String outTradeNo, double totalFee, String productId)
			throws Exception {
		int fee = (int) (totalFee * 100.00);
		Map<String, String> param = new HashMap<>(20);
		param.put("body", description);
		param.put("out_trade_no", outTradeNo);
		param.put("total_fee", fee + "");
		param.put("spbill_create_ip", getIp());
		param.put("notify_url", WXPayConfig.NOTIFY_URL);
		param.put("trade_type", "APP");
		wxPay.fillRequestData(param);
		return param;
	}

	/**
	 * 返回参数设置
	 * @param outTradeNo
	 * @return
	 * @throws Exception
	 */
	public Map<String, String> wxParamBack(String outTradeNo) throws Exception {
		Map<String, String> param = new HashMap<>(16);
		param.put("out_trade_no", outTradeNo);
		wxPay.fillRequestData(param);
		return param;
	}

	private String getIp() {
		InetAddress ia;
		try {
			ia = InetAddress.getLocalHost();
			return ia.getHostAddress();
		} catch (Exception e) {
			return null;
		}
	}

	public String errorMsg(Map<String, String> responseMap) {
		if (responseMap == null) {
			return "统一下单失败";
		}
		if ("FAIL".equals(responseMap.get("return_code"))) {
			return responseMap.get("return_msg");
		}
		return null;
	}

	public boolean isError(Map<String, String> responseMap){
		return responseMap == null || "FAIL".equals(responseMap.get("return_code"));
	}

	public boolean selectPayStatus(Map xmlToMap) {
		boolean b=true;
		String resultCode = Orgin.getString(xmlToMap, "result_code");
		String tradeNo = Orgin.getString(xmlToMap, "out_trade_no");
		int totalFee = Orgin.getIntValue(xmlToMap, "total_fee");

		Map<String, Object> tradeByNo = cgOrderDao.selectTradeByNo(tradeNo);
		String outTradeNo = Orgin.getString(tradeByNo, "trade_no");
		int orderType = Orgin.getIntValue(tradeByNo, "order_type");
		String createUserId = Orgin.getString(tradeByNo, "create_user");
		if (tradeByNo!=null){
			int paymentReal = Orgin.getIntValue(tradeByNo, "payment_real");
			if(totalFee==paymentReal&&resultCode.equals("SUCCESS")){
				//更新状态为成功
				cgOrderDao.updateTradePayStatus(tradeNo,1,orderType);
				logger.info("微信支付成功，signVerified=true, params:{}", xmlToMap);
				if(orderType == Constants.ORDER_INSURANCE){
					tsSsInsuranceDao.updatePayStatus(outTradeNo);
				}
				if(orderType == Constants.ORDER_CERTIFICATE){
					tsSsInsuranceDao.updateCertificatePayStatus(outTradeNo);
				}
				if(orderType == Constants.ORDER_WORK){
					Map<String,Object> reqMap = new HashMap<>();
					Map<String,Object> orderMap = cgOrderDao.getOrder(outTradeNo);
					Map<String,Object> currentUser = cgOrderDao.getUserById(createUserId);
					if("1".equals(currentUser.get("r_id").toString())){
						reqMap.put("u_s_id", currentUser.get("id").toString());
					}
					reqMap.put("s_id", currentUser.get("s_id").toString());
					reqMap.put("r_id", currentUser.get("r_id").toString());
					reqMap.put("id", currentUser.get("id").toString());
					reqMap.put("user_name", currentUser.get("user_name").toString());
					reqMap.put("remaining_sum", currentUser.get("remaining_sum").toString());
					reqMap.put("credit_limit", currentUser.get("credit_limit").toString());
					reqMap.put("order_id",orderMap.get("id").toString());
					reqMap.put("s_id",orderMap.get("s_id").toString());
					reqMap.put("payment_type",2);
					reqMap.put("payment_status",2);
					reqMap.put("payment_amount",totalFee/100);
					reqMap.put("order_status",17);
					reqMap.put("rc_status",1);
					appService.updateOrderInfo(reqMap);
				}
				b= true;
			}else if (totalFee!=paymentReal){
				logger.info("微信支付失败，signVerified=false, params:{}", xmlToMap);
				cgOrderDao.updateTradePayStatus(tradeNo,2,orderType);
				b= false;
			}
		}
		return b;
	}

	public String selectPayStatusAli(Map requestParams) {
		// 获取支付宝的支付key
		boolean flag = this.checkSignature(requestParams);
		try {
			if (flag){
				logger.info(">>>支付宝回调签名认证成功");
				//商户订单号
				String outTradeNo = Orgin.getString(requestParams, "out_trade_no");
				//交易状态
				String trade_status = Orgin.getString(requestParams, "trade_status");
				//交易金额
				double amount = Orgin.getDoubleValue(requestParams, "total_amount");
				int amountintValue = new Double(amount * 100).intValue();
				Map<String, Object> tradeByNo = cgOrderDao.selectTradeByNo(outTradeNo);
				int paymentReal = Orgin.getIntValue(tradeByNo, "payment_real");
				int orderType = Orgin.getIntValue(tradeByNo, "order_type");
				if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
					logger.info("支付宝回调支付成功，trade_status:{}", trade_status);


					if(amountintValue==paymentReal){
						//更新状态为成功
						cgOrderDao.updateTradePayStatus(outTradeNo,1,orderType);
						if(orderType == Constants.ORDER_INSURANCE){
                            logger.info("保险支付成功，trade_status:{}", trade_status);
							tsSsInsuranceDao.updatePayStatus(outTradeNo);
						}
						if(orderType == Constants.ORDER_CERTIFICATE){
                            logger.info("操作证支付成功，trade_status:{}", trade_status);
							tsSsInsuranceDao.updateCertificatePayStatus(outTradeNo);
						}
                        if(orderType == Constants.ORDER_WORK){
                            logger.info("工单支付成功，trade_status:{}", trade_status);
							String passbackParams = requestParams.get("passback_params").toString();
							Map<String,Object> reqMap = (Map<String,Object>)JSONObject.parse(passbackParams);
							appService.updateOrderInfo(reqMap);
                            //tsSsInsuranceDao.updateCertificatePayStatus(outTradeNo);
                        }

					}

					// 修改订单状态成功
					logger.info("支付宝支付回调修改订单、支付状态成功，结果码：" + trade_status + ",支付单号：" + outTradeNo);

				} else {
					//更新状态为成功
					cgOrderDao.updateTradePayStatus(outTradeNo,2,orderType);
					logger.error("没有处理支付宝回调业务，支付宝交易状态：{},params:{}", trade_status, requestParams);
				}

            }else {
				logger.info("支付宝回调签名认证失败，signVerified=false, params:{}", requestParams);
				return "failure";
			}
		} catch (Exception e) {
			return "failure";
		}
		return "success";
	}

	public static String setXML(String return_code, String return_msg) {
		return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
	}

	public boolean checkSignature(Map<String, String> requestParams) {
		try {
			boolean flag = AlipaySignature.rsaCheckV1(requestParams, alipay_public_key, AlipayConfig.charset,
					AlipayConfig.sign_type);
			return flag;
		} catch (Exception e) {
			return false;
		}
	}

	public void insertAliPay(Map<String, Object> reqMap) throws MyException {
		if (reqMap.containsKey("payType")){
			String outTradeNo = Orgin.getString(reqMap, "orderId");
			Integer payType=0;
			double paymentAmount=0;
			double payMoney=0;
			long couponId=0l;
			if ( reqMap.containsKey("payMoney")){
				payMoney = Double.parseDouble(reqMap.get("payMoney").toString());
			}
			if (reqMap.containsKey("paymentAmount")){
				paymentAmount = Double.parseDouble(reqMap.get("paymentAmount").toString());
			}
			if (reqMap.containsKey("couponId")){
				couponId = Orgin.getLongValue(reqMap, "couponId");
			}

			if (reqMap.containsKey("payType")){
				payType = Integer.valueOf(reqMap.get("payType").toString());
			}
			if (couponId!=0){
				UserCouponEntity entity = userCouponDao.selectById(couponId);
				PromotionCouponEntity couponEntity =
						promotionCouponDao.selectById(entity.getCouponId());
				if (couponEntity.getUseScope()!=payType){
					throw new MyException(Constants.CODE_HANDEL_FAILED, "该类别不可使用");
				}
			}
			Map<String, Object> tradeByNo = cgOrderDao.selectTradeByNo(outTradeNo);
			if (tradeByNo==null){
				cgOrderDao.insertCertificateOrderPay(OrderPay.builder()
						.paymentAmount(new Double(paymentAmount*100).intValue())
						.paymentReal(new Double(payMoney*100).intValue())
						.couponId(couponId)
						.paymentType(2)
						.paymentTime(new Date())
						.tradeNo(outTradeNo)
						.orderType(payType)
						.isRefund(1)
						.build());
				if (couponId!=0){
					userCouponDao.updateById(UserCouponEntity.builder()
							.id(couponId)
							.useFlag(2)
							.build());
				}
			}
		}
	}
}
